﻿using System;
using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using System.Globalization;
using System.Runtime.InteropServices;
using System.Text;
using System.Windows;
using System.Windows.Forms.Integration;
using System.Windows.Interop;
using System.Windows.Forms;

namespace Bookvar.AddIns.Facebook
{
    [System.Windows.Markup.ContentProperty("Child")]
    public class FormHost : HwndHost
    {
        private System.Windows.Forms.Form child;

        public event EventHandler<ChildChangedEventArgs> ChildChanged;

        public System.Windows.Forms.Form Child
        {
            get { return child; }
            set
            {
                HwndSource ps = PresentationSource.FromVisual(this) as HwndSource;
                if (ps != null && ps.Handle != IntPtr.Zero)
                    throw new InvalidOperationException("Cannot set the Child property after the layout is done.");
                System.Windows.Forms.Form oldChild = child;
                child = value;
                OnChildChanged(oldChild);
            }
        }

        public Boolean ShowCaption
        {
            get
            {
                CheckChildValidity(child);
                return (GetWindowStyle(Child.Handle) & WindowStyles.WS_BORDER) == WindowStyles.WS_CAPTION;
            }
            set
            {
                if (child == null)
                {
                    this.ChildChanged += delegate
                    {
                        if (value)
                        {
                            SetWindowStyle(Child.Handle, GetWindowStyle(Child.Handle) | WindowStyles.WS_CAPTION);
                        }
                        else
                        {
                            SetWindowStyle(Child.Handle, GetWindowStyle(Child.Handle) & ~WindowStyles.WS_CAPTION);
                        }
                    };
                }
                else
                {
                    if (value)
                    {
                        SetWindowStyle(Child.Handle, GetWindowStyle(Child.Handle) | WindowStyles.WS_CAPTION);
                    }
                    else
                    {
                        SetWindowStyle(Child.Handle, GetWindowStyle(Child.Handle) & ~WindowStyles.WS_CAPTION);
                    }
                }
            }
        }

        protected override HandleRef BuildWindowCore(HandleRef hwndParent)
        {
            CheckChildValidity(child);
            HandleRef childHwnd = new HandleRef(Child, child.Handle);
            SetWindowStyle(childHwnd.Handle, WindowStyles.WS_CHILD | GetWindowStyle(childHwnd.Handle));
            WindowsFormsHost.EnableWindowsFormsInterop();
            System.Windows.Forms.Application.EnableVisualStyles();
            NativeMethods.SetParent(childHwnd.Handle, hwndParent.Handle);
            return childHwnd;
        }

        protected override void DestroyWindowCore(HandleRef hwnd)
        {
            child.Dispose();
        }

        protected void OnChildChanged(System.Windows.Forms.Form oldChild)
        {
            if (this.ChildChanged != null)
            {
                this.ChildChanged(this, new ChildChangedEventArgs(oldChild));
            }
        }

        private static void CheckChildValidity(Form child)
        {
            if (child == null || child.Handle == IntPtr.Zero)
            {
                throw new ArgumentNullException( "child", "child form cannot be null" );
            }
        }

        [SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "Gwl")]
        public static readonly Int32 GwlStyle = -16;
        //public static readonly UInt32 WSChild = 0x40000000;

		internal static WindowStyles GetWindowStyle(IntPtr hWnd)
        {
            return (WindowStyles)NativeMethods.GetWindowLong(hWnd, GwlStyle);
        }

		internal static void SetWindowStyle(IntPtr hWnd, WindowStyles windowStyle)
        {
			UInt32 result = NativeMethods.SetWindowLong(hWnd, GwlStyle, (UInt32) windowStyle);
			if (result == 0)
			{
			    throw new InvalidOperationException( String.Format( CultureInfo.CurrentCulture,
			                                                        "Interop method SetWindowLong returned {0}", result ) );
			}
        }
        
    }

    [Flags]
    internal enum WindowStyles : uint
    {
        WS_OVERLAPPED = 0x00000000,
        WS_POPUP = 0x80000000,
        WS_CHILD = 0x40000000,
        WS_MINIMIZE = 0x20000000,
        WS_VISIBLE = 0x10000000,
        WS_DISABLED = 0x08000000,
        WS_CLIPSIBLINGS = 0x04000000,
        WS_CLIPCHILDREN = 0x02000000,
        WS_MAXIMIZE = 0x01000000,
        WS_BORDER = 0x00800000,
        WS_DLGFRAME = 0x00400000,
        WS_VSCROLL = 0x00200000,
        WS_HSCROLL = 0x00100000,
        WS_SYSMENU = 0x00080000,
        WS_THICKFRAME = 0x00040000,
        WS_GROUP = 0x00020000,
        WS_TABSTOP = 0x00010000,

        WS_MINIMIZEBOX = 0x00020000,
        WS_MAXIMIZEBOX = 0x00010000,

        WS_CAPTION = WS_BORDER | WS_DLGFRAME,
        WS_TILED = WS_OVERLAPPED,
        WS_ICONIC = WS_MINIMIZE,
        WS_SIZEBOX = WS_THICKFRAME,
        WS_TILEDWINDOW = WS_OVERLAPPEDWINDOW,

        WS_OVERLAPPEDWINDOW = WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU | WS_THICKFRAME | WS_MINIMIZEBOX | WS_MAXIMIZEBOX,
        WS_POPUPWINDOW = WS_POPUP | WS_BORDER | WS_SYSMENU,
        WS_CHILDWINDOW = WS_CHILD,
    }

}
